package k8s_ui

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/wonderivan/logger"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var K8s_ConfigMap k8s_configmap

type k8s_configmap struct{}

// 定义configmapCreate结构体，用于创建configmap需要的参数属性的定义
type ConfigMapCreate struct {
	Name      string `json:"name"`
	Namespace string `json:"namespace"`
	//ConfigMapData map[string]string `json:"items"`
	ConfigMapData []ConfigItem `json:"items"`
}

type ConfigItem struct {
	Name     string `json:"name"`
	DataYaml string `json:"datayaml"`
}

// 定义configmapNp类型，用于返回namespace中configmap的数量
type configmapNp struct {
	Namespace string `json:"configmapname"`
	DaemonNum int    `json:"configmap_num"`
}

type ConfigMapsResp struct {
	Items []corev1.ConfigMap `json:"items"`
	Total int                `json:"total"`
}

// 查询configmap
func (p *k8s_configmap) GetConfigMaps(filterName, namespace string, limit, page int) (configmapResp *ConfigMapsResp, err error) {
	//获取configmapList类型的configmap列表
	configmapList, err :=
		K8s.ClientSet.CoreV1().ConfigMaps(namespace).List(context.TODO(),
			metav1.ListOptions{})
	if err != nil {
		logger.Error(errors.New("获取configmap列表失败, " + err.Error()))
		return nil, errors.New("获取configmap列表失败, " + err.Error())
	}

	//将configmapList中的config列表(Items)，放进dataselector对象中，进行排序
	selectableData := &DataSelector{
		GenericDataList: p.toCells(configmapList.Items),
		DataSelect: &DataSelectQuery{
			Filter: &FilterQuery{Name: filterName},
			Paginate: &PaginateQuery{
				Limit: limit,
				Page:  page,
			},
		},
	}
	filtered := selectableData.Filter()
	total := len(filtered.GenericDataList)
	data := filtered.Sort().Paginate()
	//将[]DataCell类型的configmap列表转为configmap列表
	configmaps := p.fromCells(data.GenericDataList)
	return &ConfigMapsResp{
		Items: configmaps,
		Total: total,
	}, nil
}

// toCells方法用于将pod类型转成DataCell类型
func (*k8s_configmap) toCells(std []corev1.ConfigMap) []DataCell {
	cells := make([]DataCell, len(std))
	for i := range std {
		//std[i]原生pod类型 -> podCell -> DataCell
		cells[i] = configmapCell(std[i])
	}
	return cells
}

// fromCells方法用于将DataCell类型转成pod类型
func (*k8s_configmap) fromCells(cells []DataCell) []corev1.ConfigMap {
	configmaps := make([]corev1.ConfigMap, len(cells))
	for i := range cells {
		//cells[i] DataCell接口类型 -> podCell -> 原生pod类型
		configmaps[i] = corev1.ConfigMap(cells[i].(configmapCell))
	}
	return configmaps
}

// 获取configmap详情
func (d *k8s_configmap) GetConfigMapDetail(configmapName, namespace string) (configmap *corev1.ConfigMap, err error) {
	configmap, err =
		K8s.ClientSet.CoreV1().ConfigMaps(namespace).Get(context.TODO(), configmapName,
			metav1.GetOptions{})
	if err != nil {
		logger.Error(errors.New("获取configmap详情失败, " + err.Error()))
		return nil, errors.New("获取configmap详情失败, " + err.Error())
	}
	return configmap, nil
}

// 创建configmap接收configmapCreate对象
func (d *k8s_configmap) CreateConfigMap(data *ConfigMapCreate) (err error) {
	configMap := make(map[string]string)

	for _, item := range data.ConfigMapData {
		configMap[item.Name] = item.DataYaml
	}

	//将data中的数据组装成corev1.configmap对象
	configmap := &corev1.ConfigMap{
		//ObjectMeta中定义资源名、命名空间以及标签
		ObjectMeta: metav1.ObjectMeta{
			Name:      data.Name,
			Namespace: data.Namespace,
		},
		//Spec中定义类型，端口，选择器
		//Data: data.ConfigMapData,
		Data: configMap,
	}
	//创建configmap
	_, err = K8s.ClientSet.CoreV1().ConfigMaps(data.Namespace).Create(context.TODO(), configmap, metav1.CreateOptions{})
	if err != nil {
		logger.Error(errors.New("创建configmap失败, " + err.Error()))
		return errors.New("创建configmap失败, " + err.Error())
	}
	return nil
}

// 删除configmap
func (d *k8s_configmap) DeleteConfigMap(configmapName, namespace string) (err error) {
	err = K8s.ClientSet.CoreV1().ConfigMaps(namespace).Delete(context.TODO(),
		configmapName, metav1.DeleteOptions{})
	if err != nil {
		logger.Error(errors.New("删除configmap失败, " + err.Error()))
		return errors.New("删除configmap失败, " + err.Error())
	}

	return nil
}

// 更新configmap
func (d *k8s_configmap) UpdateConfigMap(namespace, content string) (err error) {
	var configmap = &corev1.ConfigMap{}
	err = json.Unmarshal([]byte(content), configmap)
	if err != nil {
		logger.Error(errors.New("反序列化失败, " + err.Error()))
		return errors.New("反序列化失败, " + err.Error())
	}
	_, err = K8s.ClientSet.CoreV1().ConfigMaps(namespace).Update(context.TODO(),
		configmap, metav1.UpdateOptions{})
	if err != nil {
		logger.Error(errors.New("更新configmap失败, " + err.Error()))
		return errors.New("更新configmap失败, " + err.Error())
	}
	return nil
}

// 获取每个namespace的configmap数量
func (d *k8s_configmap) GetConfigMapNumPerNp() (configmapNps []*configmapNp, err error) {
	namespaceList, err := K8s.ClientSet.CoreV1().Namespaces().List(context.TODO(),
		metav1.ListOptions{})
	if err != nil {
		return nil, err
	}
	for _, namespace := range namespaceList.Items {
		configmapList, err :=
			K8s.ClientSet.CoreV1().ConfigMaps(namespace.Name).List(context.TODO(),
				metav1.ListOptions{})
		if err != nil {
			return nil, err
		}
		configmapNp := &configmapNp{
			Namespace: namespace.Name,
			DaemonNum: len(configmapList.Items),
		}
		configmapNps = append(configmapNps, configmapNp)
	}
	return configmapNps, nil
}
